package com.cjack.frenchexcel.service.consumer;

import com.cjack.frenchexcel.util.HttpClientUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 调用mooncard的api
 */
@Service
public class MooncardConsumer {

    @Value( "${mooncard.serverurl}")
    private String serverurl;
    @Value( "${mooncard.username}")
    private String username;
    @Value( "${mooncard.password}")
    private String password;
    @Value( "${mooncard.clientID}")
    private String client_id;
    @Value( "${mooncard.clientSecret}")
    private String client_secret;
    @Value( "${mooncard.company_id}")
    private String company_id;

    private final static Logger LOG = LogManager.getLogger( MooncardConsumer.class);

    private String token;//mooncard接口交互需要的token
    private long tokenExpireTime;//token的过期时间

    /**
     * 获取用于mooncard接口请求的 Oauth2 password模式的的token
     * @return
     * @throws Exception
     */
    public String token() throws Exception {
        if( System.currentTimeMillis() > tokenExpireTime){//token已经过期
            StringBuilder sb = new StringBuilder( serverurl).append( "/oauth/token");
            sb.append( "?grant_type=").append( "password");
            sb.append( "&username=").append( username);
            sb.append( "&password=").append( password);
            sb.append( "&client_id=").append( client_id);
            sb.append( "&client_secret=").append( client_secret);
            sb.append( "&company_id=").append( company_id);
            JSONObject header = new JSONObject();
            header.put( "Content-Type", "application/x-www-form-urlencoded");
            LOG.info( "token,url-------------------------------" + sb.toString());
            LOG.info( "token,header-------------------------------" + header.toString());
            String response = HttpClientUtil.doPost( sb.toString(), header, null);
            LOG.info( "getToken,response-------------------------------" + response);
            JSONObject json = JSONObject.fromObject( response);
            token = json.getString( "access_token");
            tokenExpireTime = System.currentTimeMillis() + json.getInt( "expires_in") * 1000;//计算token过期时间
        }
        return "Bearer " + token;
    }

    //查询所有账户的信息
    public JSONArray accounts(){
        try {
            String url = serverurl + "/api/v3/accounts";
            JSONObject header = new JSONObject();
            header.put( "authorization", token());
            LOG.info( "accounts,url-------------------------------" + url);
            LOG.info( "accounts,header-------------------------------" + header.toString());
            String response = HttpClientUtil.httpGet( url, header);
            LOG.info( "accounts,response-------------------------------" + response);
            return JSONArray.fromObject( response);
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error( e);
        }
        return null;
    }

    /**
     * 获取mooncard下面的账户的id
     * @return
     */
    public String getAccountId() throws Exception {
        JSONArray accounts = accounts();//现在只有一个账户，直接取第一条数据即可
        if( accounts != null && accounts.size() > 0){
            return accounts.getJSONObject( 0).getString( "id");
        }
        throw new Exception( "调用mooncard的accounts接口获取账户信息失败");
    }

    /**
     * 查询账户下 对应时间范围内的交易流水
     * @param startTime  查询的开始时间
     * @param endTime  查询的结束时间  必须是 2019-11-24T23:05:57.000Z 这种格式
     * @return
     */
    public JSONArray account_movements( String startTime, String endTime){
        try {
            String accountId = getAccountId();
            String url = serverurl + "/api/v3/account_movements";
            StringBuilder sb = new StringBuilder( url);
            sb.append( "?account_id=").append( accountId);
            sb.append( "&account_movement_search%5Btransaction_date_gteq%5D=").append( startTime);
            sb.append( "&account_movement_search%5Btransaction_date_lteq%5D=").append( endTime);
            sb.append( "&per_page=").append( 1000);
            JSONObject header = new JSONObject();
            header.put( "authorization", token());
            LOG.info( "account_movements,url-------------------------------" + url);
            LOG.info( "account_movements,header-------------------------------" + header.toString());
            String response = HttpClientUtil.httpGet( sb.toString(), header);
            LOG.info( "account_movements,response-------------------------------" + response);
            return JSONArray.fromObject( response);
        } catch (Exception e) {
            LOG.error( e);
        }
        return null;
    }

    /**
     * 查询账户下 对应时间范围内即时的交易流水,此方法有别于account_movements方法，此方法是实时查询的数据，account_movements方法查询的数据有延迟
     * @param startTime  查询的开始时间
     * @param endTime  查询的结束时间  必须是 2019-11-24T23:05:57.000Z 这种格式
     * @return
     */
    public JSONArray expenses( String startTime, String endTime){
        try {
            String url = serverurl + "/api/v3/expenses";
            StringBuilder sb = new StringBuilder( url);
            sb.append( "?expense_search%5Bat_gteq%5D=").append( startTime);
            sb.append( "&expense_search%5Bat_lteq%5D=").append( endTime);
            sb.append( "&per_page=").append( 1000);

            JSONObject header = new JSONObject();
            header.put( "authorization", token());
            LOG.info( "expenses,url-------------------------------" + sb.toString());
            LOG.info( "expenses,header-------------------------------" + header.toString());
            String response = HttpClientUtil.httpGet( sb.toString(), header);
            LOG.info( "expenses,response-------------------------------" + response);
            return JSONArray.fromObject( response);
        } catch (Exception e) {
            LOG.error( e);
        }
        return null;
    }

    //查询所有银行卡的信息
    public JSONArray cards(){
        try {
            String url = serverurl + "/api/v3/cards?per_page=1000&card_search%5Bstatus_eq%5D=activated";
            JSONObject header = new JSONObject();
            header.put( "authorization", token());
            LOG.info( "cards,url-------------------------------" + url);
            LOG.info( "cards,header-------------------------------" + header.toString());
            String response = HttpClientUtil.httpGet( url, header);
            LOG.info( "cards,response-------------------------------" + response);
            return JSONArray.fromObject( response);
        } catch (Exception e) {
            LOG.error( e);
        }
        return null;
    }

    /**
     * 设置mooncard卡的 月、周、日额度
     * @param userId
     * @param cardId
     * @param monthLimit
     * @param weeklyLimit
     * @param dayLimit
     */
    public void putCard( Long userId, String cardId, Integer monthLimit, Integer weeklyLimit, Integer dayLimit){
        try {
            JSONObject param = new JSONObject();
            JSONObject card = new JSONObject();
            card.put( "threshold_daily", dayLimit);
            card.put( "threshold_weekly", weeklyLimit);
            card.put( "threshold_monthly", monthLimit);
            param.put( "card", card.toString());
            String url = serverurl + "/api/v3/cards/" + cardId;
            JSONObject header = new JSONObject();
            header.put( "authorization", token());
            LOG.info( "-----------userID:" + userId + ",putCard,url-------------------------------" + url);
            LOG.info( "-----------userID:" + userId + "putCard,header-------------------------------" + header.toString());
            LOG.info( "-----------userID:" + userId + "putCard,param-------------------------------" + param.toString());
            String response = HttpClientUtil.doPut( url, header, param.toString());
            LOG.info( "-----------userID:" + userId + "putCard,response-------------------------------" + response);
        } catch (Exception e) {
            LOG.error( e.getMessage(),e);
        }
    }
}
